package com.suyang.syt.weixin;

import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.log4j.Logger;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import com.suyang.syt.context.BeanFactoryContext;
import com.suyang.syt.model.WeixinGroup;
import com.suyang.syt.model.WeixinMsgReceive;
import com.suyang.syt.model.WeixinUser;
import com.suyang.syt.model.dto.WeixinMenuDTO;
import com.suyang.syt.util.DateFormat;
import com.suyang.syt.util.EmptyUtil;
import com.suyang.syt.util.HttpTookit;
import com.suyang.syt.util.JsonUtil;
import com.suyang.syt.util.PropertiesUtil;

public class WeixinKit {
	private static final Logger logger = Logger.getLogger(WeixinKit.class);
	private static final String CONTENT_TYPE_JSON = "application/json";

	/** 应用ID */
	private static String AppID;
	/** 应用密钥 */
	private static String AppSecret;

	/** 文本消息类型 */
	public static String MSG_TEXT;
	/** 图片消息类型 */
	public static String MSG_IMAGE;
	/** 语音消息类型 */
	public static String MSG_VOICE;
	/** 视频消息类型 */
	public static String MSG_VIDEO;
	/** 被动回复消息音乐类型 */
	public static String MSG_MUSIC;
	/** 被动回复消息图文小心 */
	public static String MSG_NEWS;
	/** 小视频消息类型 */
	public static String MSG_SHORTVIDEO;
	/** 地理位置消息类型 */
	public static String MSG_LOCATION;
	/** 链接消息类型 */
	public static String MSG_LINK;
	/** 事件消息类型 */
	public static String MSG_EVENT;
	/** 订阅事件类型 */
	public static String EVENT_SUBSCRIBE;
	/** 取消订阅事件类型 */
	public static String EVENT_UNSUBSCRIBE;
	/** 用户已关注时的事件推送 */
	public static String EVENT_SCAN;
	/** 上报地理位置事件 */
	public static String EVENT_LOCATION;
	/** 点击菜单拉取消息时的事件推送 */
	public static String EVENT_CLICK;
	/** 点击菜单跳转链接时的事件推送 */
	public static String EVENT_VIEW;
	/** 扫码推事件的事件推送 */
	public static String EVENT_SCANCODE_PUSH;
	/** 扫码推事件且弹出“消息接收中”提示框的事件推送 */
	public static String EVENT_SCANCODE_WAITMSG;
	/** 弹出系统拍照发图的事件推送 */
	public static String EVENT_PIC_SYSPHOTO;
	/** 弹出拍照或者相册发图的事件推送 */
	public static String EVENT_PIC_PHOTO_OR_ALBUM;
	/** 弹出微信相册发图器的事件推送 */
	public static String EVENT_PIC_WEIXIN;
	/** 弹出地理位置选择器的事件推送 */
	public static String EVENT_LOCATION_SELECT;

	/** 获取access_token的URL */
	private static String access_token;
	/** 创建菜单的URL */
	private static String create_menu;
	/** 上传media的URL */
	private static String upload_media;
	/** 上传永久图文素材的URL */
	private static String upload_news;
	/** 上传永久素材的URL */
	private static String upload_material;
	/** 获取media的URL */
	private static String get_media;
	/** 发送模版消息的URL */
	private static String send_template;
	/** 创建分组的URL */
	private static String create_group;
	/** 查询所有分组的URL */
	private static String list_group;
	/** 删除分组的URL */
	private static String delete_group;
	/** 修改分组名的URL */
	private static String update_group;
	/** 通过用户的OpenID查询其所在的GroupID的URL */
	private static String getid_group;
	/** 批量移动用户到分组的URL */
	private static String batchmove_group;
	/** 获取用户列表的URL */
	private static String list_user;
	/** 批量获取用户信息的URL */
	private static String update_batch_user;
	/** 更新用户备注的URL */
	private static String update_remark_user;
	/** 用户授权URL */
	private static String authorize;
	/** 用户授权时,获取用户openid的URL */
	private static String authorize_auth;
	/** 创建二维码URL */
	private static String create_qrcode;

	static {
		try {
			Properties properties = PropertiesUtil.getProperties("WeixinContext.properties");
			AppID = properties.getProperty("AppID");
			AppSecret = properties.getProperty("AppSecret");

			MSG_TEXT = properties.getProperty("MSG_TEXT");
			MSG_IMAGE = properties.getProperty("MSG_IMAGE");
			MSG_VOICE = properties.getProperty("MSG_VOICE");
			MSG_VIDEO = properties.getProperty("MSG_VIDEO");
			MSG_MUSIC = properties.getProperty("MSG_MUSIC");
			MSG_NEWS = properties.getProperty("MSG_NEWS");
			MSG_SHORTVIDEO = properties.getProperty("MSG_SHORTVIDEO");
			MSG_LOCATION = properties.getProperty("MSG_LOCATION");
			MSG_LINK = properties.getProperty("MSG_LINK");
			MSG_EVENT = properties.getProperty("MSG_EVENT");
			EVENT_SUBSCRIBE = properties.getProperty("EVENT_SUBSCRIBE");
			EVENT_UNSUBSCRIBE = properties.getProperty("EVENT_UNSUBSCRIBE");
			EVENT_SCAN = properties.getProperty("EVENT_SCAN");
			EVENT_LOCATION = properties.getProperty("EVENT_LOCATION");
			EVENT_CLICK = properties.getProperty("EVENT_CLICK");
			EVENT_VIEW = properties.getProperty("EVENT_VIEW");
			EVENT_SCANCODE_PUSH = properties.getProperty("EVENT_SCANCODE_PUSH");
			EVENT_SCANCODE_WAITMSG = properties.getProperty("EVENT_SCANCODE_WAITMSG");
			EVENT_PIC_SYSPHOTO = properties.getProperty("EVENT_PIC_SYSPHOTO");
			EVENT_PIC_PHOTO_OR_ALBUM = properties.getProperty("EVENT_PIC_PHOTO_OR_ALBUM");
			EVENT_PIC_WEIXIN = properties.getProperty("EVENT_PIC_WEIXIN");
			EVENT_LOCATION_SELECT = properties.getProperty("EVENT_LOCATION_SELECT");

			access_token = properties.getProperty("access_token");
			create_menu = properties.getProperty("create_menu");
			upload_media = properties.getProperty("upload_media");
			upload_news = properties.getProperty("upload_news");
			upload_material = properties.getProperty("upload_material");
			get_media = properties.getProperty("get_media");
			send_template = properties.getProperty("send_template");
			create_group = properties.getProperty("create_group");
			list_group = properties.getProperty("list_group");
			delete_group = properties.getProperty("delete_group");
			getid_group = properties.getProperty("getid_group");
			update_group = properties.getProperty("update_group");
			batchmove_group = properties.getProperty("batchmove_group");
			list_user = properties.getProperty("list_user");
			update_batch_user = properties.getProperty("update_batch_user");
			update_remark_user = properties.getProperty("update_remark_user");
			authorize = properties.getProperty("authorize");
			authorize_auth = properties.getProperty("authorize_auth");
			create_qrcode = properties.getProperty("create_qrcode");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private WeixinKit() {

	}

	private static String replaceURL(String url, String APPID, String APPSECRET, String ACCESS_TOKEN, String TYPE, String MEDIA_ID) {
		if (EmptyUtil.isNotEmpty(url)) {
			if (EmptyUtil.isNotEmpty(APPID)) {
				url = url.replace("APPID", APPID);
			}
			if (EmptyUtil.isNotEmpty(APPSECRET)) {
				url = url.replace("APPSECRET", APPSECRET).replace("SECRET", APPSECRET);
			}
			if (EmptyUtil.isNotEmpty(ACCESS_TOKEN)) {
				url = url.replace("ACCESS_TOKEN", ACCESS_TOKEN);
			}
			if (EmptyUtil.isNotEmpty(TYPE)) {
				url = url.replace("TYPE", TYPE);
			}
			if (EmptyUtil.isNotEmpty(MEDIA_ID)) {
				url = url.replace("MEDIA_ID", MEDIA_ID);
			}
		}
		return url;
	}

	/** 读取xml字符串,解析xml,返回WeixinReceiveMsg对象 */
	public static WeixinMsgReceive doParseXML(InputStream inputStream) throws Exception {
		XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser();
		pullParser.setInput(inputStream, "UTF-8");
		int event = pullParser.getEventType();
		WeixinMsgReceive receiveMsg = new WeixinMsgReceive();
		while (event != XmlPullParser.END_DOCUMENT) {
			switch (event) {
			case XmlPullParser.START_DOCUMENT:
				break;
			case XmlPullParser.START_TAG:
				if ("ToUserName".equals(pullParser.getName())) {
					receiveMsg.setToUserName(pullParser.nextText());
				} else if ("FromUserName".equals(pullParser.getName())) {
					receiveMsg.setFromUserName(pullParser.nextText());
				} else if ("CreateTime".equals(pullParser.getName())) {
					receiveMsg.setCreateTime(Long.parseLong(pullParser.nextText()));
				} else if ("MsgType".equals(pullParser.getName())) {
					receiveMsg.setMsgType(pullParser.nextText());
				} else if ("Content".equals(pullParser.getName())) {
					receiveMsg.setContent(pullParser.nextText());
				} else if ("MsgId".equals(pullParser.getName())) {
					receiveMsg.setMsgId(Long.parseLong(pullParser.nextText()));
				} else if ("PicUrl".equals(pullParser.getName())) {
					receiveMsg.setPicUrl(pullParser.nextText());
				} else if ("MediaId".equals(pullParser.getName())) {
					receiveMsg.setMediaId(pullParser.nextText());
				} else if ("Format".equals(pullParser.getName())) {
					receiveMsg.setFormat(pullParser.nextText());
				} else if ("Recognition".equals(pullParser.getName())) {
					receiveMsg.setRecognition(pullParser.nextText());
				} else if ("ThumbMediaId".equals(pullParser.getName())) {
					receiveMsg.setThumbMediaId(pullParser.nextText());
				} else if ("Location_X".equals(pullParser.getName())) {
					receiveMsg.setLocation_X(pullParser.nextText());
				} else if ("Location_Y".equals(pullParser.getName())) {
					receiveMsg.setLocation_Y(pullParser.nextText());
				} else if ("Scale".equals(pullParser.getName())) {
					receiveMsg.setScale(pullParser.nextText());
				} else if ("Label".equals(pullParser.getName())) {
					receiveMsg.setLabel(pullParser.nextText());
				} else if ("Title".equals(pullParser.getName())) {
					receiveMsg.setTitle(pullParser.nextText());
				} else if ("Description".equals(pullParser.getName())) {
					receiveMsg.setDescription(pullParser.nextText());
				} else if ("Url".equals(pullParser.getName())) {
					receiveMsg.setUrl(pullParser.nextText());
				} else if ("Event".equals(pullParser.getName())) {
					receiveMsg.setEvent(pullParser.nextText());
				} else if ("EventKey".equals(pullParser.getName())) {
					receiveMsg.setEventKey(pullParser.nextText());
				} else if ("Ticket".equals(pullParser.getName())) {
					receiveMsg.setTicket(pullParser.nextText());
				} else if ("Latitude".equals(pullParser.getName())) {
					receiveMsg.setLatitude(pullParser.nextText());
				} else if ("Longitude".equals(pullParser.getName())) {
					receiveMsg.setLongitude(pullParser.nextText());
				} else if ("Precision".equals(pullParser.getName())) {
					receiveMsg.setPrecision(pullParser.nextText());
				} else if ("ScanType".equals(pullParser.getName())) {
					receiveMsg.setScanType(pullParser.nextText());
				} else if ("ScanResult".equals(pullParser.getName())) {
					receiveMsg.setScanResult(pullParser.nextText());
				} else if ("Count".equals(pullParser.getName())) {
					receiveMsg.setCount(pullParser.nextText());
				} else if ("PicMd5Sum".equals(pullParser.getName())) {
					String picMd5Sum = receiveMsg.getPicMd5Sum();
					if (EmptyUtil.isEmpty(picMd5Sum)) {
						receiveMsg.setPicMd5Sum(pullParser.nextText());
					} else {
						picMd5Sum += "," + pullParser.nextText();
						receiveMsg.setPicMd5Sum(picMd5Sum);
					}
				} else if ("Poiname".equals(pullParser.getName())) {
					receiveMsg.setPoiname(pullParser.nextText());
				}
				break;
			case XmlPullParser.END_TAG:
				break;
			}
			event = pullParser.next();
		}
		return receiveMsg;
	}

	/** 获取access_token */
	public static String getAccessToken() {
		String url = replaceURL(access_token, AppID, AppSecret, null, null, null);
		String content = HttpTookit.doGet(url, null);
		if (EmptyUtil.isNotEmpty(content)) {
			WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
			if (message != null && EmptyUtil.isEmpty(message.getErrcode())) {
				return message.getAccess_token();
			} else {
				logger.error("调用getAccessToken发生异常:" + content);
			}
		}
		return null;
	}

	/** 创建菜单 */
	public static boolean createMenu(List<WeixinMenuDTO> datas) {
		String url = replaceURL(create_menu, null, null, BeanFactoryContext.getAccessToken(), null, null);
		Map<String, List<WeixinMenuDTO>> map = new HashMap<String, List<WeixinMenuDTO>>();
		map.put("button", datas);
		String json = JsonUtil.toJson(map);
		String content = HttpTookit.doPostEntity(url, json, CONTENT_TYPE_JSON);
		WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
		if (message != null && "0".equals(message.getErrcode())) {
			return true;
		}
		logger.error("调用createMenu发生异常:" + content);
		return false;
	}

	/** 根据Map创建XML格式的字符串 */
	public static String createXML(Map<String, String> map) {
		StringBuilder sb = new StringBuilder();
		sb.append("<xml>");
		Set<String> keys = map.keySet();
		if (EmptyUtil.isNotEmpty(keys)) {
			for (String key : keys) {
				sb.append("<").append(key).append(">");
				sb.append(map.get(key));
				sb.append("</").append(key).append(">");
			}
		}
		sb.append("</xml>");
		return sb.toString();
	}

	/** 上传临时素材,返回Media_id */
	public static String uploadMedia(String path, String type) {
		String url = replaceURL(upload_media, null, null, BeanFactoryContext.getAccessToken(), type, null);
		String content = HttpTookit.doPostFile(url, "media", path);
		WeixinMessage weixinMessage = JsonUtil.fromJson(content, WeixinMessage.class);
		if (weixinMessage != null && EmptyUtil.isEmpty(weixinMessage.getErrcode())) {
			System.out.println(DateFormat.dateToString(new Date()) + "上传了临时素材:" + content);
			if ("thumb".equals(type)) {
				return weixinMessage.getThumb_media_id();
			} else {
				return weixinMessage.getMedia_id();
			}
		}
		logger.error("调用uploadMedia发生异常:" + content);
		return null;
	}

	/** 上传永久图文素材,返回Media_id */
	public static String uploadNews(String json) {
		System.out.println(json);
		String url = replaceURL(upload_news, null, null, BeanFactoryContext.getAccessToken(), null, null);
		String content = HttpTookit.doPostEntity(url, json, CONTENT_TYPE_JSON);
		WeixinMessage weixinMessage = JsonUtil.fromJson(content, WeixinMessage.class);
		if (weixinMessage != null && EmptyUtil.isEmpty(weixinMessage.getErrcode())) {
			System.out.println(DateFormat.dateToString(new Date()) + "上传了图文素材:" + content);
			return weixinMessage.getMedia_id();
		}
		logger.error("调用uploadNews发生异常:" + content);
		return null;
	}

	/** 上传永久素材,返回Media_id */
	public static WeixinMessage uploadMaterial(String path, String type) {
		String url = replaceURL(upload_material, null, null, BeanFactoryContext.getAccessToken(), type, null);
		String content = HttpTookit.doPostFile(url, "media", path);
		WeixinMessage weixinMessage = JsonUtil.fromJson(content, WeixinMessage.class);
		if (weixinMessage != null && EmptyUtil.isEmpty(weixinMessage.getErrcode())) {
			System.out.println(DateFormat.dateToString(new Date()) + "上传了永久素材:" + content);
			return weixinMessage;
		}
		logger.error("调用uploadMaterial发生异常:" + content);
		return null;
	}

	/** 上传永久素材,返回Media_id(视频video类型) */
	public static WeixinMessage uploadMaterialVideo(String path, String json) {
		String url = replaceURL(upload_material, null, null, BeanFactoryContext.getAccessToken(), "video", null);
		String content = HttpTookit.doPostFileEntity(url, "media", path, "description", json, CONTENT_TYPE_JSON);
		WeixinMessage weixinMessage = JsonUtil.fromJson(content, WeixinMessage.class);
		if (weixinMessage != null && EmptyUtil.isEmpty(weixinMessage.getErrcode())) {
			System.out.println(DateFormat.dateToString(new Date()) + "上传了永久素材(视频):" + content);
			return weixinMessage;
		}
		logger.error("调用uploadMaterialVideo发生异常:" + content);
		return null;
	}

	/** 获取媒体文件,并将文件写入到参数file中 */
	public static void getMedia(String media_id, File file) {
		String url = replaceURL(get_media, null, null, BeanFactoryContext.getAccessToken(), null, media_id);
		HttpTookit.doGet(url, null, "UTF-8", file);
	}

	/** 发送模版消息 */
	public static boolean sendTemplate(WeixinTemplateMessage weixinTemplateMessage) {
		String url = replaceURL(send_template, null, null, BeanFactoryContext.getAccessToken(), null, null);
		String content = HttpTookit.doPostEntity(url, JsonUtil.toJson(weixinTemplateMessage), CONTENT_TYPE_JSON);
		WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
		if (message != null && "0".equals(message.getErrcode())) {
			return true;
		}
		logger.error("调用sendTemplate发生异常:" + content);
		return false;
	}

	/** 创建分组 */
	public static WeixinGroup createGroup(String name) {
		String url = replaceURL(create_group, null, null, BeanFactoryContext.getAccessToken(), null, null);
		StringBuilder sb = new StringBuilder();
		sb.append("{\"group\":");
		sb.append("{");
		sb.append("\"name\":");
		sb.append("\"").append(name).append("\"");
		sb.append("}");
		sb.append("}");
		String content = HttpTookit.doPostEntity(url, sb.toString(), CONTENT_TYPE_JSON);
		WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
		if (message != null && EmptyUtil.isEmpty(message.getErrcode())) {
			return message.getGroup();
		}
		logger.error("调用createGroup发生异常:" + content);
		return null;
	}

	/** 查询所有分组信息 */
	public static List<WeixinGroup> listGroup() {
		String url = replaceURL(list_group, null, null, BeanFactoryContext.getAccessToken(), null, null);
		String content = HttpTookit.doGet(url, null);
		WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
		if (message != null && EmptyUtil.isNotEmpty(message.getErrcode())) {
			logger.error("调用listGroup发生异常:" + content);
			return null;
		}
		return message.getGroups();
	}

	/** 删除分组(注意本接口是删除一个用户分组，删除分组后，所有该分组内的用户自动进入默认分组) */
	public static boolean deleteGroup(int id) {
		String url = replaceURL(delete_group, null, null, BeanFactoryContext.getAccessToken(), null, null);
		StringBuilder sb = new StringBuilder();
		sb.append("{\"group\":");
		sb.append("{");
		sb.append("\"id\":");
		sb.append(id);
		sb.append("}");
		sb.append("}");
		String content = HttpTookit.doPostEntity(url, sb.toString(), CONTENT_TYPE_JSON);
		WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
		if (message != null && EmptyUtil.isNotEmpty(message.getErrmsg()) && !"ok".equals(message.getErrmsg())) {
			logger.error("调用deleteGroup发生异常:" + content);
			return false;
		}
		return true;
	}

	/** 修改分组名 */
	public static boolean updateGroup(int id, String name) {
		String url = replaceURL(update_group, null, null, BeanFactoryContext.getAccessToken(), null, null);
		StringBuilder sb = new StringBuilder();
		sb.append("{\"group\":");
		sb.append("{");
		sb.append("\"id\":");
		sb.append(id);
		sb.append(",");
		sb.append("\"name\":");
		sb.append("\"").append(name).append("\"");
		sb.append("}");
		sb.append("}");
		String content = HttpTookit.doPostEntity(url, sb.toString(), CONTENT_TYPE_JSON);
		WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
		if (message != null && EmptyUtil.isNotEmpty(message.getErrmsg()) && !"ok".equals(message.getErrmsg())) {
			logger.error("调用updateGroup发生异常:" + content);
			return false;
		}
		return true;
	}

	/** 根据用户ID获取用户所在组ID */
	public static int getGroupId(String openid) {
		String url = replaceURL(getid_group, null, null, BeanFactoryContext.getAccessToken(), null, null);
		StringBuilder sb = new StringBuilder();
		sb.append("{\"openid\":\"");
		sb.append(openid);
		sb.append("\"}");
		String content = HttpTookit.doPostEntity(url, sb.toString(), CONTENT_TYPE_JSON);
		WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
		if (message != null && EmptyUtil.isNotEmpty(message.getErrmsg()) && !"ok".equals(message.getErrmsg())) {
			logger.error("调用getGroupId发生异常:" + content);
			return -1;
		}
		return message.getGroupid();
	}

	/** 批量移动用户到别的分组中 */
	public static boolean updateBatchmoveGroup(String openid_list, int to_groupid) {
		String url = replaceURL(batchmove_group, null, null, BeanFactoryContext.getAccessToken(), null, null);
		Map<String, Object> map = new HashMap<String, Object>();
		if (EmptyUtil.isNotEmpty(openid_list)) {
			map.put("openid_list", openid_list.split(","));
		}
		map.put("to_groupid", to_groupid);
		System.out.println(JsonUtil.toJson(map));
		String content = HttpTookit.doPostEntity(url, JsonUtil.toJson(map), CONTENT_TYPE_JSON);
		WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
		if (message != null && EmptyUtil.isNotEmpty(message.getErrmsg()) && !"ok".equals(message.getErrmsg())) {
			logger.error("调用updateBatchmoveGroup发生异常:" + content);
			return false;
		}
		return true;
	}

	public static WeixinUserPager listUser(String next_openid) {
		String url = replaceURL(list_user, null, null, BeanFactoryContext.getAccessToken(), null, null);
		String content = "";
		try {
			if (EmptyUtil.isEmpty(next_openid)) {
				content = HttpTookit.doGet(url, null);
			} else {
				Map<String, String> map = new HashMap<String, String>();
				map.put("next_openid", next_openid);
				content = HttpTookit.doGet(url, map);
			}
			WeixinUserPager userPager = JsonUtil.fromJson(content, WeixinUserPager.class);
			if (userPager != null && userPager.getTotal() > 0) {
				return userPager;
			}
			logger.error("调用listUser发生异常:" + content);
		} catch (Exception e) {
			logger.error("调用listUser发生异常:" + content);
			logger.error("调用listUser发生异常:" + e.getMessage(), e);
		}
		return null;
	}

	public static List<WeixinUser> updateBatchUser(String ids) {
		if (EmptyUtil.isNotEmpty(ids)) {
			String[] idsArr = ids.split(",");
			if (EmptyUtil.isNotEmpty(idsArr) && idsArr.length <= 100) {
				List<Map<String, String>> list = new ArrayList<Map<String, String>>();
				Map<String, String> map = null;
				for (String id : idsArr) {
					map = new HashMap<String, String>();
					map.put("openid", id);
					map.put("lang", "zh-CN");
					list.add(map);
				}
				Map<String, List<Map<String, String>>> user_list = new HashMap<String, List<Map<String, String>>>();
				user_list.put("user_list", list);
				String url = replaceURL(update_batch_user, null, null, BeanFactoryContext.getAccessToken(), null, null);
				String content = HttpTookit.doPostEntity(url, JsonUtil.toJson(user_list), CONTENT_TYPE_JSON);
				WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
				if (message != null && EmptyUtil.isNotEmpty(message.getErrmsg()) && !"ok".equals(message.getErrmsg())) {
					logger.error("调用updateBatchUser发生异常:" + content);
					return null;
				}
				return message.getUser_info_list();
			}
		}
		return null;
	}

	public static boolean updateRemarkUser(String openid, String remark) {
		String url = replaceURL(update_remark_user, null, null, BeanFactoryContext.getAccessToken(), null, null);
		Map<String, String> map = new HashMap<String, String>();
		map.put("openid", openid);
		map.put("remark", remark);
		String content = HttpTookit.doPostEntity(url, JsonUtil.toJson(map), CONTENT_TYPE_JSON);
		WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
		if (message != null && "0".equals(message.getErrcode())) {
			return true;
		}
		logger.error("调用sendTemplate发生异常:" + content);
		return false;
	}

	public static String replaceAuthorizeURI(String REDIRECT_URI) throws UnsupportedEncodingException {
		String url = replaceURL(authorize, AppID, null, BeanFactoryContext.getAccessToken(), null, null);
		url = url.replace("REDIRECT_URI", URLEncoder.encode(REDIRECT_URI, "UTF-8")).replace("SCOPE", "snsapi_base").replace("STATE", "syt2015");
		System.out.println(url);
		return url;
	}

	public static String authorize(String code) {
		String url = replaceURL(authorize_auth, AppID, AppSecret, BeanFactoryContext.getAccessToken(), null, null);
		url = url.replace("CODE", code);
		String content = HttpTookit.doGet(url, null);
		WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
		if (message != null && EmptyUtil.isEmpty(message.getErrmsg())) {
			return message.getOpenid();
		}
		logger.error("调用authorize发生异常:" + content);
		return null;
	}

	public static WeixinMessage createQrcode(int type, long scene_id, String scene_str) {
		StringBuilder json = new StringBuilder();
		if (type == 0) {
			// 临时二维码
			json.append("{\"expire_seconds\":600,\"action_name\":\"QR_SCENE\",\"action_info\":{\"scene\":{\"scene_id\":");
			json.append(scene_id);
			json.append("}}}");
		} else if (type == 1) {
			// 永久二维码
			json.append("{\"action_name\":\"QR_LIMIT_STR_SCENE\",\"action_info\":{\"scene\":{\"scene_str\":\"");
			json.append(scene_str);
			json.append("\"}}}");
		}
		String url = replaceURL(create_qrcode, null, null, BeanFactoryContext.getAccessToken(), null, null);
		String content = HttpTookit.doPostEntity(url, json.toString(), CONTENT_TYPE_JSON);
		WeixinMessage message = JsonUtil.fromJson(content, WeixinMessage.class);
		if (message != null && EmptyUtil.isNotEmpty(message.getErrmsg()) && !"ok".equals(message.getErrmsg())) {
			logger.error("调用createQrcode发生异常:" + content);
			return null;
		}
		return message;
	}

}
